﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using Dsl.Ped.Framework.Common;
using Dsl.Ped.Framework.Projections.ConstantProjections;

namespace Dsl.Ped.Framework.Projections
{
    /// <summary>
    /// Factory for the creation of constant-based projections
    /// </summary>
    public class ConstantProjectionFactory : ProjectionFactoryBase
    {
        /// <summary>
        /// Initializes properly constant-based projection
        /// </summary>
        /// <typeparam name="T">Type of the projection (TextBox, Label, etc.)</typeparam>
        /// <param name="projectionHint">Hint for the creation of a projection</param>
        /// <param name="source">Source object of the projection</param>
        /// <param name="type">Type of a property which the projection is bound to</param>
        /// <returns><see cref="FrameworkElement"/> representing the constant-based projection</returns>
        public static FrameworkElement InitializeConstantProjection<T>(
            IConstantProjectionHint<T> projectionHint, object source, Type type)
            where T : FrameworkElement, new()
        {
            var projection = InitializeProjection(projectionHint, type);

            if (projectionHint.ValueProperty != null)
            {
                projection.SetValue(projectionHint.ValueProperty, source);
            }

            var adornerDecorator = new AdornerDecorator { Child = projection };
            return adornerDecorator;
        }

        #region Empty

        /// <summary>
        /// Gets the empty projection
        /// </summary>
        /// <returns>Empty projection</returns>
        public static IProjection GetEmptyProjection()
        {
            return new Projection() { View = new Control() };
        }

        #endregion

        #region Label

        /// <summary>
        /// Gets the <see cref="Label"/> projection. Projection in which bounds the object into a <see cref="Label"/>
        /// </summary>
        /// <param name="source">Source object</param>
        /// <param name="customConfiguration">Custom configuration applied to the <see cref="Label"/> instance</param>
        /// <returns>Label projection</returns>
        public static IProjection GetLabelProjection(object source, Action<Label> customConfiguration = null)
        {
            var projectionHint = new ConstantProjectionHint<Label>(
                Label.ContentProperty,
                null,
                customConfiguration);
            return new Projection()
                       {
                           View = InitializeConstantProjection(
                                projectionHint, 
                                source, 
                                source != null ? source.GetType() : typeof(string))
                       };
        }

        #endregion

        #region TextBlock

        /// <summary>
        /// Gets the <see cref="TextBox"/> projection. Projection in which bounds the object into a <see cref="TextBox"/>
        /// </summary>
        /// <param name="source">Source object</param>
        /// <param name="customConfiguration">Custom configuration applied to the <see cref="TextBox"/> instance</param>
        /// <returns>TextBox projection</returns>
        public static IProjection GetTextBlockProjection(object source, Action<Label> customConfiguration)
        {
            var projectionHint = new ConstantProjectionHint<Label>(
                TextBlock.TextProperty,
                null,
                customConfiguration);
            return new Common.Projection()
                       {
                           View = InitializeConstantProjection(
                                projectionHint, 
                                source, 
                                source != null ? source.GetType() : typeof(string))
                       };
        }

        #endregion
    }
}
